unit AfterDownload_RuleForm;

interface

uses
  AfterDownload_Defines,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, Grids, StdCtrls, ExtCtrls, CheckLst;

type
  TAD_RuleForm = class(TForm)
    LE_Title: TLabeledEdit;
    Label1: TLabel;
    SG_Cond: TStringGrid;
    SB_AddCond: TSpeedButton;
    SB_DelCond: TSpeedButton;
    LE_Formula: TLabeledEdit;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    SB_Test: TSpeedButton;
    CB_Others: TCheckBox;
    CLB_Actions: TCheckListBox;
    Label2: TLabel;
    SB_AddAct: TSpeedButton;
    SB_DelAct: TSpeedButton;
    SB_ActUp: TSpeedButton;
    SB_ActDn: TSpeedButton;
    SB_EditCond: TSpeedButton;
    SB_EditAct: TSpeedButton;
    SB_ActTop: TSpeedButton;
    SB_ActBottom: TSpeedButton;
    SB_TestRule: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    procedure SB_TestClick(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure SG_CondClick(Sender: TObject);
    procedure LE_TitleChange(Sender: TObject);
    procedure LE_FormulaChange(Sender: TObject);
    procedure CB_OthersClick(Sender: TObject);
    procedure SB_AddCondClick(Sender: TObject);
    procedure SB_DelCondClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SG_CondDblClick(Sender: TObject);
    procedure SB_EditCondClick(Sender: TObject);
    procedure CLB_ActionsClick(Sender: TObject);
    procedure SB_ActUpClick(Sender: TObject);
    procedure SB_ActDnClick(Sender: TObject);
    procedure SB_AddActClick(Sender: TObject);
    procedure CLB_ActionsDblClick(Sender: TObject);
    procedure SB_EditActClick(Sender: TObject);
    procedure SB_DelActClick(Sender: TObject);
    procedure CLB_ActionsClickCheck(Sender: TObject);
    procedure SB_ActTopClick(Sender: TObject);
    procedure SB_ActBottomClick(Sender: TObject);
    procedure SB_TestRuleClick(Sender: TObject);
  private
    { Private declarations }
    FRule: Rule;
    Lang: String;
    sDeleteCond: String;
    sTitleNoEmpty: String;
    sDeleteAct: String;
    sCondNoEmpty: String;
    sActNoEmpty: String;
    FActionByDefault: Boolean;
    procedure SetLanguage(language: String);
    procedure TranslateToo;
    procedure SetRule(ARule: Rule);
    procedure UpdateConditions;
    function IsFormula(ShowResult: Boolean = false): Boolean;
    procedure BitBtnClick(BitBtn: TBitBtn);
    procedure CheckCondButtons;
    function EditCondition(Idx: Integer): Boolean;
    procedure UpdateMyActions(SetIndex: Integer = -1);
    procedure CheckActButtons;
    function EditAction(Idx: Integer): Boolean;
  public
    { Public declarations }
    property Language: String write SetLanguage;
    property myRule: Rule read FRule write SetRule;
    property ActionByDefault: Boolean read FActionByDefault write FActionByDefault default false;
  end;

var
  AD_RF: TAD_RuleForm = nil;

implementation

{$R *.dfm}

uses
 gnugettext,
 Locales,
 formula,
 AfterDownload_ConditionForm,
 AfterDownload_ActionForm,
 AfterDownload_TestRuleForm;

procedure TAD_RuleForm.FormCreate(Sender: TObject);
begin
 FRule:=Rule.Create(nil);
 //
 SG_Cond.ColWidths[1]:=100;
 SG_Cond.ColWidths[2]:=200;
 SG_Cond.Cells[0, 0]:=_('No.'); //Number
 SG_Cond.Cells[1, 0]:=_('Type');
 SG_Cond.Cells[2, 0]:=_('Parameter');
 //
 TranslateComponent(Self);
end;

procedure TAD_RuleForm.SetLanguage(language: String);
begin
 Lang:=language;
 TranslateForm(Self, Language, TranslateToo);
end;

procedure TAD_RuleForm.TranslateToo;
begin
 SG_Cond.Cells[0, 0]:=_('No.'); //Number
 SG_Cond.Cells[1, 0]:=_('Type');
 SG_Cond.Cells[2, 0]:=_('Parameter');
 //
 sDeleteCond:=_('Are you sure to delete condition %s ?');
 sTitleNoEmpty:=_('Title cannot be empty!');
 sDeleteAct:=_('Are you sure to delete action "%s %s"?');
 sCondNoEmpty:=_('Condition list cannot be empty!');
 sActNoEmpty:=_('Action list cannot be empty!');
 //
 BitBtn2.Caption:=_('Cancel');
end;

procedure TAD_RuleForm.SetRule(ARule: Rule);
begin
 FRule.Assign(ARule);
 //
 LE_Title.Text:=FRule.Title;
 LE_Formula.Text:=FRule.Formula;
 CB_Others.Checked:=FRule.Others;
 UpdateConditions;
 UpdateMyActions;
end;

procedure TAD_RuleForm.UpdateConditions;
 var
  i: Integer;
begin
 i:=FRule.Conditions.Count;
 if i>0 then
   SG_Cond.RowCount:=i+1
 else
  begin
   SG_Cond.RowCount:=2;
   SG_Cond.Cells[0, 1]:='';
   SG_Cond.Cells[1, 1]:='';
   SG_Cond.Cells[2, 1]:='';
  end;
 for i:=0 to FRule.Conditions.Count-1 do
  begin
   SG_Cond.Cells[0, i+1]:=FRule.Conditions[i].CondIndex;
   SG_Cond.Cells[1, i+1]:=GetCondTypeDesc(FRule.Conditions[i].CondType);
   SG_Cond.Cells[2, i+1]:=FRule.Conditions[i].Parameter;
  end;
 CheckCondButtons;
end;

procedure TAD_RuleForm.SB_TestClick(Sender: TObject);
begin
 if LE_Formula.Text='' then
  begin
   MessageDlg(_('You must enter at least one condition code!'), mtError, [mbOK], 0);
   ActiveControl:=LE_Formula;
  end
 else
   IsFormula(true);
end;

function TAD_RuleForm.IsFormula(ShowResult: Boolean = false): Boolean;
 var
  AF: TArtFormula;
  vars: array of String;
  vals: TCalcArray;
  i, num: Integer;
begin
 Result:=false;
 AF:=TArtFormula.Create(Self);
 AF.TestUsedVars:=true;
 num:=FRule.Conditions.Count;
 SetLength(vars, num);
 SetLength(vals, num);
 for i:=0 to num-1 do
  begin
   vars[i]:=FRule.Conditions[i].CondIndex;
   setN(vals[i], 1);
  end;
 try
  if ShowResult then
    MessageDlg(_('Result:')+' '+AF.ComputeStr(LE_Formula.Text, num, @vars, @vals), mtInformation, [mbOK], 0)
  else
    AF.ComputeStr(LE_Formula.Text, num, @vars, @vals);
  Result:=true;
 except
  on E:Exception do
   begin
    MessageDlg(E.Message, mtError, [mbOK], 0);
    ActiveControl := LE_Formula;
    LE_Formula.SelStart := AF.ErrPos-1;
   end;
 end;
 AF.Free;
end;

procedure TAD_RuleForm.BitBtnClick(BitBtn: TBitBtn);
begin
 Self.ModalResult:=BitBtn.ModalResult;
 if not (fsModal in Self.FormState) then
   Self.Close;
end;

procedure TAD_RuleForm.BitBtn1Click(Sender: TObject);
begin
 BitBtnClick(BitBtn1);
end;

procedure TAD_RuleForm.BitBtn2Click(Sender: TObject);
begin
 BitBtnClick(BitBtn2);
end;

procedure TAD_RuleForm.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
 var
  i: Integer;
begin
 if ModalResult=mrOK then
  begin
   if LE_Title.Text='' then
    begin
     MessageDlg(sTitleNoEmpty, mtError, [mbOK], 0);
     ActiveControl:=LE_Title;
     CanClose:=false;
     Exit;
    end;
   //
   if not IsFormula() then
    begin
     CanClose:=false;
     Exit;
    end;
   //
   if FRule.Conditions.Count=0 then
    begin
     MessageDlg(sCondNoEmpty, mtError, [mbOK], 0);
     CanClose:=false;
     Exit;
    end;
   //
   if FRule.Actions.Count=0 then
    begin
     MessageDlg(sActNoEmpty, mtError, [mbOK], 0);
     CanClose:=false;
     Exit;
    end;
   //check for external function necessity
   FRule.ExtFunction:=nil;
   for i:=0 to FRule.Conditions.Count-1 do
    begin
     if FRule.Conditions[i].ExternalFlag then
      begin
       FRule.ExtFunction:=myFunction;
       //ShowMessage('External function is set!'); //debug
       Break;
      end;
    end;
  end;
end;

procedure TAD_RuleForm.CheckCondButtons;
 var
  i: Integer;
begin
 i:=SG_Cond.Selection.Top;
 SB_DelCond.Enabled:=(i>0) and (i<FRule.Conditions.Count+1);
 SB_AddCond.Enabled:=SG_Cond.RowCount<Length(cndIndex)+1;
 SB_EditCond.Enabled:=(i>0) and (i<FRule.Conditions.Count+1);
end;

procedure TAD_RuleForm.SG_CondClick(Sender: TObject);
begin
 CheckCondButtons;
end;

procedure TAD_RuleForm.LE_TitleChange(Sender: TObject);
begin
 FRule.Title:=LE_Title.Text;
end;

procedure TAD_RuleForm.LE_FormulaChange(Sender: TObject);
begin
 FRule.Formula:=LE_Formula.Text;
end;

procedure TAD_RuleForm.CB_OthersClick(Sender: TObject);
begin
 FRule.Others:=CB_Others.Checked;
end;

function TAD_RuleForm.EditCondition(Idx: Integer): Boolean;
 var
  New: Boolean;
  newCondition: Condition;
  newIndex: Char;
begin
 AD_CF:=TAD_ConditionForm.Create(Self);
 AD_CF.Language:=Lang;
 if (Idx>=0) then
  begin
   if Idx=FRule.Conditions.Count then
    begin
     newIndex:=GetAvailCondIndex(FRule.Conditions.GetUsedIndexes);
     newCondition:=FRule.Conditions.Add;
     newCondition.Clear;
     newCondition.CondIndex:=newIndex;
     AD_CF.myCondition:=newCondition;
     New:=true;
    end
   else
    begin
     AD_CF.myCondition:=FRule.Conditions[Idx];
     New:=false;
    end;
   Result:=AD_CF.ShowModal=mrOK;
   if Result then
     FRule.Conditions[Idx].Assign(AD_CF.myCondition)
   else
    begin
     if New then
       FRule.Conditions.Delete(FRule.Conditions.Count-1);
    end;
   FreeAndNil(AD_CF);
  end
 else
   Result:=false;
end;

procedure TAD_RuleForm.SB_AddCondClick(Sender: TObject);
begin
 if EditCondition(FRule.Conditions.Count) then
   UpdateConditions;
end;

procedure TAD_RuleForm.SB_DelCondClick(Sender: TObject);
 var
  i: Integer;
begin
 i:=SG_Cond.Selection.Top-1;
 if MessageDlg(Format(sDeleteCond, [FRule.Conditions[i].CondIndex]), mtConfirmation, [mbYes, mbNo], 0)=mrYes then
  begin
   FRule.Conditions.Delete(i);
   UpdateConditions;
  end;
end;

procedure TAD_RuleForm.FormDestroy(Sender: TObject);
begin
 FRule.Free;
end;

procedure TAD_RuleForm.UpdateMyActions(SetIndex: Integer = -1);
 var
  i, j: Integer;
begin
 CLB_Actions.Clear;
 for i:=0 to FRule.Actions.Count-1 do
  begin
   j:=CLB_Actions.Items.Add(GetActTypeDesc(FRule.Actions[i].ActType)+' '+FRule.Actions[i].Destination+' '+GetActTypeFlagDesc(FRule.Actions[i].ActType, FRule.Actions[i].Flag));
   CLB_ACtions.Checked[j]:=FRule.Actions[i].Enabled;
  end;
 if (SetIndex>=0) and (SetIndex<CLB_Actions.Items.Count) then
   CLB_Actions.ItemIndex:=SetIndex; 
 CheckActButtons;
end;

procedure TAD_RuleForm.SG_CondDblClick(Sender: TObject);
begin
 if EditCondition(SG_Cond.Selection.Top-1) then
   UpdateConditions;
end;

procedure TAD_RuleForm.SB_EditCondClick(Sender: TObject);
begin
 if EditCondition(SG_Cond.Selection.Top-1) then
   UpdateConditions;
end;

procedure TAD_RuleForm.CLB_ActionsClick(Sender: TObject);
begin
 CheckActButtons;
end;

procedure TAD_RuleForm.CheckActButtons;
 var
  i: Integer;
begin
 i:=CLB_Actions.ItemIndex;
 SB_DelAct.Enabled:=i>=0;
 SB_EditAct.Enabled:=i>=0;
 SB_ActUp.Enabled:=i>0;
 SB_ActDn.Enabled:=i<FRule.Actions.Count-1;
 SB_ActTop.Enabled:=i>0;
 SB_ActBottom.Enabled:=i<FRule.Actions.Count-1;
end;

procedure TAD_RuleForm.SB_ActUpClick(Sender: TObject);
 var
  i: Integer;
begin
 i:=CLB_Actions.ItemIndex;
 if i>0 then
  begin
   FRule.Actions.Items[i].Index:=i-1;
   UpdateMyActions(i-1);
  end;
end;

procedure TAD_RuleForm.SB_ActDnClick(Sender: TObject);
 var
  i: Integer;
begin
 i:=CLB_Actions.ItemIndex;
 if i<FRule.Actions.Count-1 then
  begin
   FRule.Actions.Items[i].Index:=i+1;
   UpdateMyActions(i+1);
  end;
end;

procedure TAD_RuleForm.SB_AddActClick(Sender: TObject);
begin
 if EditAction(FRule.Actions.Count) then
   UpdateMyActions(FRule.Actions.Count-1);
end;

procedure TAD_RuleForm.CLB_ActionsDblClick(Sender: TObject);
begin
 if EditAction(CLB_Actions.ItemIndex) then
   UpdateMyActions(CLB_Actions.ItemIndex);
end;

procedure TAD_RuleForm.SB_EditActClick(Sender: TObject);
begin
 if EditAction(CLB_Actions.ItemIndex) then
   UpdateMyActions(CLB_Actions.ItemIndex);
end;

procedure TAD_RuleForm.SB_DelActClick(Sender: TObject);
 var
  i: Integer;
begin
 i:=CLB_Actions.ItemIndex;
 if MessageDlg(Format(sDeleteAct, [GetActTypeDesc(FRule.Actions[i].ActType), FRule.Actions[i].Destination]), mtConfirmation, [mbYes, mbNo], 0)=mrYes then
  begin
   FRule.Actions.Delete(i);
   UpdateMyActions;
  end;
end;

function TAD_RuleForm.EditAction(Idx: Integer): Boolean;
 var
  New: Boolean;
  newAction: anAction;
begin
 AD_AF:=TAD_ActionForm.Create(Self);
 AD_AF.Language:=Lang;
 if (Idx>=0) then
  begin
   if Idx=FRule.Actions.Count then
    begin
     newAction:=FRule.Actions.Add;
     newAction.Clear;
     AD_AF.myAction:=newAction;
     New:=true;
    end
   else
    begin
     AD_AF.myAction:=FRule.Actions[Idx];
     New:=false;
    end;
   Result:=AD_AF.ShowModal=mrOK;
   if Result then
    begin
     FRule.Actions[Idx].Assign(AD_AF.myAction);
     if New then
       FRule.Actions[Idx].Enabled:=ActionByDefault;
    end
   else
    begin
     if New then
       FRule.Actions.Delete(FRule.Actions.Count-1);
    end;
   FreeAndNil(AD_AF);
  end
 else
   Result:=false;
end;

procedure TAD_RuleForm.CLB_ActionsClickCheck(Sender: TObject);
 var
  i: Integer;
begin
 i:=CLB_Actions.ItemIndex;
 FRule.Actions[i].Enabled:=CLB_Actions.Checked[i];
end;

procedure TAD_RuleForm.SB_ActTopClick(Sender: TObject);
 var
  i: Integer;
begin
 i:=CLB_Actions.ItemIndex;
 if i>0 then
  begin
   FRule.Actions.Items[i].Index:=0;
   UpdateMyActions(0);
  end;
end;

procedure TAD_RuleForm.SB_ActBottomClick(Sender: TObject);
 var
  i, c: Integer;
begin
 c:=FRule.Actions.Count-1;
 i:=CLB_Actions.ItemIndex;
 if i<c then
  begin
   FRule.Actions.Items[i].Index:=c;
   UpdateMyActions(c);
  end;
end;

procedure TAD_RuleForm.SB_TestRuleClick(Sender: TObject);
begin
 if not Assigned(AD_TRF) then
   AD_TRF:=TAD_TestRuleForm.Create(Self);
 //
 AD_TRF.myRule:=FRule;
 AD_TRF.Language:=Lang;
 AD_TRF.ShowModal;
 //
 FreeAndNil(AD_TRF);
end;

end.
